#include "ULUI_LookupLatestBlue.h"
#include "UL_Global.h"
#include "ULGfx_History.h"
#include <algorithm>

#define LATESTN_BLUE_LOOKUP_START_X	100
#define LATESTN_BLUE_LOOKUP_START_Y	100
#define SERIALS_PER_SCREEN	8

ULUI_LookupLatestBlue ULUI_LookupLatestBlue::latestBlueLookup;

enum HistoryLookupIDs{
	RANGE_BOX,
	OK,
	EXIT	
};	

static char *menuTitles[] = {
	"                                ",
	"确定",
	"返回",
};

#define FIXED_GAP	20

void ULUI_LookupLatestBlue::Init()
{
	int i;
	ULUI_Menu menu;
	char buf[8] = {0};

	AttachEventHandler(this);

	pad.Reset();
	pad.EnableSolidBg(true);
	menu.SetFont(UL_Global::UnionLottoFont());
	pad.SetFont(UL_Global::UnionLottoFont());
	selectedMenu = -1;

	for (i = 0; i <= EXIT; i++){
		menu.SetID(i);
		menu.SetTitle(menuTitles[i]);
		menus.AddMenu(menu);
	}

	//Find menu's X is after tip
	menu.SetTitle("                                ");
	menu.GetTitleSize(tipWidth, tipHeight);
	menus.SetFirstMenuXY(VSDL_Point(LATESTN_BLUE_LOOKUP_START_X + tipWidth, LATESTN_BLUE_LOOKUP_START_Y + tipHeight));
	pad.SetStartXY(VSDL_Point(LATESTN_BLUE_LOOKUP_START_X + tipWidth * 2 + FIXED_GAP, LATESTN_BLUE_LOOKUP_START_Y + tipHeight));
	selectedBox = RANGE_BOX;
	nSerials = serialOffset = 0;

	//Setup menus for blue numbers
	blueNumbers.SetVertical(false);
	menu.ShowBoarder(true);
	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		sprintf(buf, " %02d ", i + 1);
		menu.SetID(i);
		menu.SetTitle(buf);
		blueNumbers.AddMenu(menu);
	}

	blueNumbers.SetFirstMenuXY(VSDL_Point(LATESTN_BLUE_LOOKUP_START_X + tipWidth, LATESTN_BLUE_LOOKUP_START_Y - 2));

	selectedBlue = -1;
}

void ULUI_LookupLatestBlue::CleanUp()
{
	pad.Reset();
	menus.Reset();
	blueNumbers.Reset();
}

void ULUI_LookupLatestBlue::Pause()
{
}

void ULUI_LookupLatestBlue::Resume()
{
	selectedMenu = -1;
}

void ULUI_LookupLatestBlue::Update(VSDL_GameEngine *game)
{
	if (selectedMenu == -1){
		return ;
	}

	switch (selectedMenu){
		case OK:
			if (pad.GetString() != NULL){
				nSerials = strtoul(pad.GetString(), NULL, 10);
			}else{
				nSerials = 0;
			}
			break;
		case EXIT:
			game->PopState();
			break;
	}
}

void ULUI_LookupLatestBlue::Draw(VSDL_GameEngine *game)
{
	VSDL_RGB rgbNormal(100, 100, 100);
	VSDL_RGB rgbSelected(250, 100, 100);
	VSDL_RGB rgb;
	char *str;
	VSDL_Point currentXY(LATESTN_BLUE_LOOKUP_START_X, LATESTN_BLUE_LOOKUP_START_Y);
	SDL_Surface *destSurf = game->GetSurface();
	ULG_History *ulgHistory = ULG_History::Instance();;
	int serialNo;
	int historyY = LATESTN_BLUE_LOOKUP_START_Y + (EXIT + 3) * tipHeight;
	char buf[128];


	ulgHistory->SetStartXY(VSDL_Point(LATESTN_BLUE_LOOKUP_START_X, historyY));

	UL_Global::UnionLottoShowBg();
	UL_Global::UnionLottoShowTitle();
	menus.Show(destSurf);
	blueNumbers.Show(destSurf);
	//Draw history data background
	SPG_RectFilled(destSurf, LATESTN_BLUE_LOOKUP_START_X, historyY, destSurf->w, destSurf->h, rgbNormal.GetRGB32(destSurf));
	//Show tips
	UL_Global::UnionLottoShowTip("输入期数并选择蓝球查询", currentXY);
	currentXY.y += tipHeight;
	UL_Global::UnionLottoShowTip("期数:(例:16)", currentXY);
	
	str = pad.GetString();

	rgb = rgbSelected;

	if (str != NULL){
		UL_Global::UnionLottoShowTip(str, VSDL_Point(currentXY.x + tipWidth, currentXY.y));
	}

	SPG_Rect(destSurf, currentXY.x + tipWidth, currentXY.y, currentXY.x + tipWidth * 2, currentXY.y + tipHeight, rgb.GetRGB32(destSurf));
	rgb = rgbNormal;

	//Draw input pad
	pad.Show(destSurf);
	//Draw spliting line
	historyY--;
	SPG_Line(destSurf, currentXY.x, historyY, destSurf->w, historyY, rgbNormal.GetRGB32(destSurf));
	//Show lates N
	if (nSerials == 0 || selectedBlue == -1){
		return ;
	}
	
	list<ULC_Serial *> retList;
	list<ULC_Serial *>::iterator iter;
	ULC_Serial *serial;

	ulgHistory->GetLatestNSerialsWithBlueNumber(retList, nSerials, selectedBlue);

	if (retList.size() == 0){
		return ;
	}

	if (serialOffset >= retList.size()){
		serialOffset = retList.size() - 1;
	}

	iter = retList.begin();
	advance(iter, serialOffset);

	ulgHistory->ShowSerial(destSurf, (*iter)->sn);
	//Show gap between last serial
	currentXY.x = (destSurf->w >> 1) + FIXED_GAP + (tipWidth >> 1);
	currentXY.y = historyY;
	
	if (retList.size() == 1){
		sprintf(buf, "只有一期蓝球，无法计算间隔期数");
	}else{
		if (iter != retList.begin()){
			serial = *iter;
			iter--;
			sprintf(buf, "%d期该蓝球和上一次出现间隔%d期", serial->sn, ulgHistory->CaculateGap(serial, *iter));
		}else{
			serial = *iter;
			iter++;
			sprintf(buf, "%d期该蓝球和下一次出现间隔%d期", serial->sn, ulgHistory->CaculateGap(serial, *iter));
		}
	}

	UL_Global::UnionLottoShowTip(buf, currentXY);
	currentXY.y += tipHeight;
	
	serial = retList.back();
	ULC_Serial *latestSerial = ulgHistory->GetLatestSerial();

	int gap;	

	if (latestSerial->sortedBalls.blue == selectedBlue){
		gap = 0;
	}else{
		//Latest gap should plus 1 because we have to count the latest serial as 1
		gap = ulgHistory->CaculateGap(serial, latestSerial) + 1;
	}

	sprintf(buf, "该蓝球距离最近一次出现的间隔是%d期", gap);
	UL_Global::UnionLottoShowTip(buf, currentXY);
}

ULUI_LookupLatestBlue *ULUI_LookupLatestBlue::Instance()
{
	return &latestBlueLookup;
}


void __HANDLE_EVENT ULUI_LookupLatestBlue::OnKeyDown(SDLKey keysym, unsigned char *keyStates, void *arg)
{
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	//Basic
	if (keyStates[SDLK_ESCAPE]){
		game->PopState();
	}

	//Special cases
	if (keyStates[SDLK_RETURN]){
		selectedMenu = OK;
		return ;
	}

	if (nSerials > SERIALS_PER_SCREEN){
		if (keyStates[SDLK_PAGEUP]){
			if (serialOffset > 0){
				serialOffset--;
			}
		}

		if (keyStates[SDLK_PAGEDOWN]){
			serialOffset++;

			if (serialOffset >= nSerials){
				serialOffset = nSerials;
			}
		}
	}

	pad.PushKeysym(keysym);
}

void __HANDLE_EVENT ULUI_LookupLatestBlue::OnMouseMove(int button, unsigned char buttonState, int absX, int absY, int relX, int relY, void *arg)
{
	menus.UpdateMenuList(absX, absY);
	blueNumbers.UpdateMenuList(absX, absY);
	pad.UpdateStatus(absX, absY);
}

void __HANDLE_EVENT ULUI_LookupLatestBlue::OnMouseDown(int button, unsigned char buttonState, int absX, int absY, void *arg)
{
	int i;
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	selectedMenu = -1;

	for (i = 0; i <= EXIT; i++){
		ULUI_Menu &menu = menus.GetMenu(i);

		if (menu.IsXYInRect(absX, absY)){
			selectedMenu = i;
			break;
		}
	}

	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		ULUI_Menu &menu = blueNumbers.GetMenu(i);

		if (menu.IsXYInRect(absX, absY)){
			selectedBlue = i + 1;
		}
	}

	pad.OnMouseDown(absX, absY);

	//Special case for WHEEL
	if (button == SDL_BUTTON_WHEELUP){
		if (serialOffset > 0){
			serialOffset--;
		}
	}

	if (button == SDL_BUTTON_WHEELDOWN){
		serialOffset++;

		if (serialOffset >= nSerials){
			serialOffset = nSerials;
		}
	}

}

void __HANDLE_EVENT ULUI_LookupLatestBlue::OnQuit(void *arg)
{
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	game->Quit();
}
